﻿// Copyright (c) 2012 - 2020 Jared Zheng <jaredz at outlook dot com>
// Buddha Framework is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//          http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
//
// Create : 2012-12-01 version 0.1 Jared Zheng <jaredz at outlook dot com>
// Update : 2018-12-05 version 3.1.5 Jared Zheng <jaredz at outlook dot com>

#include "stdafx.h"
#include "exception.h"
#include "MainHandler.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////
// CServerConsole

IMPLEMENT_CLASS_LOADER( CServerConsole, NET )
IMPLEMENT_CLASS_LOADER( CServerConsole, Center )
IMPLEMENT_CLASS_LOADER( CServerConsole, Balance )
IMPLEMENT_CLASS_LOADER( CServerConsole, AuthorDB )
IMPLEMENT_CLASS_LOADER( CServerConsole, Author )
IMPLEMENT_CLASS_LOADER( CServerConsole, MasterDB )
IMPLEMENT_CLASS_LOADER( CServerConsole, Master )
IMPLEMENT_CLASS_LOADER( CServerConsole, Service )
IMPLEMENT_CLASS_LOADER( CServerConsole, Gate )

#if (__PLATFORM_TARGET__ == PLATFORM_TARGET_WINDOWS)
Int CServerConsole::ThreadExceptHandler(TId tThreadId, Int nThreadType, Int nThreadRoutine, void*, struct _EXCEPTION_POINTERS* pExceptInfo)
{
    CString strName = TF("ThreadExceptHandler");
    strName.AppendFormat(TF("[%d-%d-%d]"), tThreadId, nThreadType, nThreadRoutine);
    CSEHException::Dump(pExceptInfo, *strName);
    return EXCEPTION_CONTINUE_SEARCH;
}
#endif

CServerConsole::CServerConsole(void)
: m_FileLog(true, LOGL_ALL, nullptr, TF("ServerConsole"))
{
}

CServerConsole::~CServerConsole(void)
{
}

PCXStr CServerConsole::GetServerName(Int nIndex)
{
    switch (nIndex)
    {
    case PAKT_CENTER:
        {
            return TF("Center");
        }
        break;
    case PAKT_BALANCE:
        {
            return TF("Balance");
        }
        break;
    case PAKT_AUTHORDB:
        {
            return TF("AuthorDB");
        }
        break;
    case PAKT_AUTHOR:
        {
            return TF("Author");
        }
        break;
    case PAKT_MASTERDB:
        {
            return TF("MasterDB");
        }
        break;
    case PAKT_MASTER:
        {
            return TF("Master");
        }
        break;
    case PAKT_SERVICE:
        {
            return TF("Service");
        }
        break;
    case PAKT_GATE:
        {
            return TF("Gate");
        }
        break;
    default:
        {
            return TF("Unknown");
        }
    }
}

bool CServerConsole::Init(PCXStr pszCmd)
{
    if (pszCmd != nullptr)
    {
        m_Config.SetArgs(pszCmd);
    }
    if (m_Config.Init())
    {
        return InitSystems();
    }
    return false;
}

bool CServerConsole::Init(Int nArgc, PXStr* ppszArgv)
{
    if (nArgc > 1)
    {
        m_Config.SetArgs(nArgc, ppszArgv);
    }
    if (m_Config.Init())
    {
        return InitSystems();
    }
    return false;
}

void CServerConsole::Exit(void)
{
    StopServers();
    UnloadServers();

    ExitSystems();
    m_Config.Exit();
}

void CServerConsole::Start(void)
{
    CMainHandler MainHandler;
    if (MainHandler.Init())
    {
        m_SyncEvent.Wait();
    }
}

void CServerConsole::Stop(void)
{
    m_SyncEvent.Signal();
}

bool CServerConsole::LoadServer(Int nServer, CEventHandler* pSHandler)
{
    if (m_Config.GetLoadServers() & nServer)
    {
        assert(pSHandler != nullptr);
        CStringFix strPath;
        if (m_Config.GetServerPath(nServer, strPath) == false)
        {
            LOGV_ERROR(m_FileLog, TF("服务器类型%X在配置文件中不存在文件路径"), nServer);
            return false;
        }
        switch (nServer)
        {
        case CServerConfig::CFG_LOAD_CENTER:
            {
                if (m_CenterServer != nullptr)
                {
                    LOG_ERROR(m_FileLog, TF("加载同步管理服务器模块失败, 同步管理服务器模块已经存在"));
                    return false;
                }
                INIT_CLASS_LOADER(CServerConsole, Center, UUID_OF(CCommonServerSystem), *strPath);
                LOADER_CLASS_CREEATE(CServerConsole, Center, UUID_OF(ICenterServer), m_CenterServer.Cast<CComponent>());
                if ((m_CenterServer == nullptr) || (m_CenterServer->Init(*pSHandler, m_Config) != RET_OKAY))
                {
                    LOG_ERROR(m_FileLog, TF("加载同步管理服务器模块失败"));
                    return false;
                }
                LOG_INFO(m_FileLog, TF("加载同步管理服务器模块完成"));
                pSHandler->OnHandle(PAKT_CENTER, reinterpret_cast<uintptr_t>(m_CenterServer.Get()), 0);
            }
            break;
        case CServerConfig::CFG_LOAD_BALANCE:
            {
                if (m_BalanceServer != nullptr)
                {
                    LOG_ERROR(m_FileLog, TF("加载授权均衡服务器模块失败, 授权均衡服务器模块已经存在"));
                    return false;
                }
                INIT_CLASS_LOADER(CServerConsole, Balance, UUID_OF(CCommonServerSystem), *strPath);
                LOADER_CLASS_CREEATE(CServerConsole, Balance, UUID_OF(IBalanceServer), m_BalanceServer.Cast<CComponent>());
                if ((m_BalanceServer == nullptr) || (m_BalanceServer->Init(*pSHandler, m_Config) != RET_OKAY))
                {
                    LOG_ERROR(m_FileLog, TF("加载授权均衡服务器模块失败"));
                    return false;
                }
                LOG_INFO(m_FileLog, TF("加载授权均衡服务器模块完成"));
                pSHandler->OnHandle(PAKT_BALANCE, reinterpret_cast<uintptr_t>(m_BalanceServer.Get()), 0);
            }
            break;
        case CServerConfig::CFG_LOAD_AUTHORDB:
            {
                if (m_AuthorDBServer != nullptr)
                {
                    LOG_ERROR(m_FileLog, TF("加载授权数据服务器模块失败, 授权数据服务器模块已经存在"));
                    return false;
                }
                INIT_CLASS_LOADER(CServerConsole, AuthorDB, UUID_OF(CCommonServerSystem), *strPath);
                LOADER_CLASS_CREEATE(CServerConsole, AuthorDB, UUID_OF(IAuthorDBServer), m_AuthorDBServer.Cast<CComponent>());
                if ((m_AuthorDBServer == nullptr) || (m_AuthorDBServer->Init(*pSHandler, m_Config) != RET_OKAY))
                {
                    LOG_ERROR(m_FileLog, TF("加载授权数据服务器模块失败"));
                    return false;
                }
                LOG_INFO(m_FileLog, TF("加载授权数据服务器模块完成"));
                pSHandler->OnHandle(PAKT_AUTHORDB, reinterpret_cast<uintptr_t>(m_AuthorDBServer.Get()), 0);
            }
            break;
        case CServerConfig::CFG_LOAD_AUTHOR:
            {
                if (m_AuthorServer != nullptr)
                {
                    LOG_ERROR(m_FileLog, TF("加载授权网关服务器模块失败, 授权网关服务器模块已经存在"));
                    return false;
                }
                INIT_CLASS_LOADER(CServerConsole, Author, UUID_OF(CCommonServerSystem), *strPath);
                LOADER_CLASS_CREEATE(CServerConsole, Author, UUID_OF(IAuthorServer), m_AuthorServer.Cast<CComponent>());
                if ((m_AuthorServer == nullptr) || (m_AuthorServer->Init(*pSHandler, m_Config) != RET_OKAY))
                {
                    LOG_ERROR(m_FileLog, TF("加载授权网关服务器模块失败"));
                    return false;
                }
                LOG_INFO(m_FileLog, TF("加载授权网关服务器模块完成"));
                pSHandler->OnHandle(PAKT_AUTHOR, reinterpret_cast<uintptr_t>(m_AuthorServer.Get()), 0);
            }
            break;
        case CServerConfig::CFG_LOAD_MASTERDB:
            {
                if (m_MasterDBServer != nullptr)
                {
                    LOG_ERROR(m_FileLog, TF("加载业务数据服务器模块失败, 业务数据服务器模块已经存在"));
                    return false;
                }
                INIT_CLASS_LOADER(CServerConsole, MasterDB, UUID_OF(CCommonServerSystem), *strPath);
                LOADER_CLASS_CREEATE(CServerConsole, MasterDB, UUID_OF(IMasterDBServer), m_MasterDBServer.Cast<CComponent>());
                if ((m_MasterDBServer == nullptr) || (m_MasterDBServer->Init(*pSHandler, m_Config) != RET_OKAY))
                {
                    LOG_ERROR(m_FileLog, TF("加载业务数据服务器模块失败"));
                    return false;
                }
                LOG_INFO(m_FileLog, TF("加载业务数据服务器模块完成"));
                pSHandler->OnHandle(PAKT_MASTERDB, reinterpret_cast<uintptr_t>(m_MasterDBServer.Get()), 0);
            }
            break;
        case CServerConfig::CFG_LOAD_MASTER:
            {
                if (m_MasterServer != nullptr)
                {
                    LOG_ERROR(m_FileLog, TF("加载业务管理服务器模块失败, 业务管理服务器模块已经存在"));
                    return false;
                }
                INIT_CLASS_LOADER(CServerConsole, Master, UUID_OF(CCommonServerSystem), *strPath);
                LOADER_CLASS_CREEATE(CServerConsole, Master, UUID_OF(IMasterServer), m_MasterServer.Cast<CComponent>());
                if ((m_MasterServer == nullptr) || (m_MasterServer->Init(*pSHandler, m_Config) != RET_OKAY))
                {
                    LOG_ERROR(m_FileLog, TF("加载业务管理服务器模块失败"));
                    return false;
                }
                LOG_INFO(m_FileLog, TF("加载业务管理服务器模块完成"));
                pSHandler->OnHandle(PAKT_MASTER, reinterpret_cast<uintptr_t>(m_MasterServer.Get()), 0);
            }
            break;
        case CServerConfig::CFG_LOAD_SERVICE:
            {
                if (m_ServiceServer != nullptr)
                {
                    LOG_ERROR(m_FileLog, TF("加载业务功能服务器模块失败, 业务功能服务器模块已经存在"));
                    return false;
                }
                INIT_CLASS_LOADER(CServerConsole, Service, UUID_OF(CCommonServerSystem), *strPath);
                LOADER_CLASS_CREEATE(CServerConsole, Service, UUID_OF(IServiceServer), m_ServiceServer.Cast<CComponent>());
                if ((m_ServiceServer == nullptr) || (m_ServiceServer->Init(*pSHandler, m_Config) != RET_OKAY))
                {
                    LOG_ERROR(m_FileLog, TF("加载业务功能服务器模块失败"));
                    return false;
                }
                LOG_INFO(m_FileLog, TF("加载业务功能服务器模块完成"));
                pSHandler->OnHandle(PAKT_SERVICE, reinterpret_cast<uintptr_t>(m_ServiceServer.Get()), 0);
            }
            break;
        case CServerConfig::CFG_LOAD_GATE:
            {
                if (m_GateServer != nullptr)
                {
                    LOG_ERROR(m_FileLog, TF("加载业务网关服务器模块失败, 业务网关服务器模块已经存在"));
                    return false;
                }
                INIT_CLASS_LOADER(CServerConsole, Gate, UUID_OF(CCommonServerSystem), *strPath);
                LOADER_CLASS_CREEATE(CServerConsole, Gate, UUID_OF(IGateServer), m_GateServer.Cast<CComponent>());
                if ((m_GateServer == nullptr) || (m_GateServer->Init(*pSHandler, m_Config) != RET_OKAY))
                {
                    LOG_ERROR(m_FileLog, TF("加载业务网关服务器模块失败"));
                    return false;
                }
                LOG_INFO(m_FileLog, TF("加载业务网关服务器模块完成"));
                pSHandler->OnHandle(PAKT_GATE, reinterpret_cast<uintptr_t>(m_GateServer.Get()), 0);
            }
            break;
        default:
            {
                LOGV_WARN(m_FileLog, TF("未知的服务器类型%X"), nServer);
                return false;
            }
        }
        return true;
    }
    else
    {
        LOGV_WARN(m_FileLog, TF("服务器类型%X在配置文件中不存在加载配置"), nServer);
    }
    return false;
}

void CServerConsole::UnloadServers(void)
{
    if (m_GateServer != nullptr)
    {
        m_GateServer->Exit();
        m_GateServer = nullptr;
        LOG_INFO(m_FileLog, TF("卸载业务网关服务器模块完成"));
    }
    if (m_ServiceServer != nullptr)
    {
        m_ServiceServer->Exit();
        m_ServiceServer = nullptr;
        LOG_INFO(m_FileLog, TF("卸载业务功能服务器模块完成"));
    }
    if (m_MasterServer != nullptr)
    {
        m_MasterServer->Exit();
        m_MasterServer = nullptr;
        LOG_INFO(m_FileLog, TF("卸载业务管理服务器模块完成"));
    }
    if (m_MasterDBServer != nullptr)
    {
        m_MasterDBServer->Exit();
        m_MasterDBServer = nullptr;
        LOG_INFO(m_FileLog, TF("卸载业务数据服务器模块完成"));
    }
    if (m_AuthorServer != nullptr)
    {
        m_AuthorServer->Exit();
        m_AuthorServer = nullptr;
        LOG_INFO(m_FileLog, TF("卸载授权网关服务器模块完成"));
    }
    if (m_AuthorDBServer != nullptr)
    {
        m_AuthorDBServer->Exit();
        m_AuthorDBServer = nullptr;
        LOG_INFO(m_FileLog, TF("卸载授权数据服务器模块完成"));
    }
    if (m_BalanceServer != nullptr)
    {
        m_BalanceServer->Exit();
        m_BalanceServer = nullptr;
        LOG_INFO(m_FileLog, TF("卸载授权均衡服务器模块完成"));
    }
    if (m_CenterServer != nullptr)
    {
        m_CenterServer->Exit();
        m_CenterServer = nullptr;
        LOG_INFO(m_FileLog, TF("卸载同步管理服务器模块完成"));
    }
    EXIT_CLASS_LOADER( CServerConsole, Center );
    EXIT_CLASS_LOADER( CServerConsole, Balance );
    EXIT_CLASS_LOADER( CServerConsole, AuthorDB );
    EXIT_CLASS_LOADER( CServerConsole, Author );
    EXIT_CLASS_LOADER( CServerConsole, MasterDB );
    EXIT_CLASS_LOADER( CServerConsole, Master );
    EXIT_CLASS_LOADER( CServerConsole, Service );
    EXIT_CLASS_LOADER( CServerConsole, Gate );
}

bool CServerConsole::StartServers(void)
{
    if (m_NetworkPtr != nullptr)
    {
        CNETTraits::NET_ATTR attr;
        attr.nAttrs     = m_Config.GetNetworkAttr();
        attr.nThread    = m_Config.GetNetworkThread();
        attr.nAckTime   = m_Config.GetNetworkAck();
        attr.nTimeout   = m_Config.GetNetworkTimeout();
        attr.nMaxBuffer = m_Config.GetNetworkBuffer();
        attr.nMaxJumbo  = m_Config.GetNetworkJumbo();
        if (attr.nAttrs & CNETTraits::ATTR_NAGLE)
        {
            attr.nAttrs &= (~CNETTraits::ATTR_NAGLE); // 去掉ATTR_NAGLE, 保持心态包的即使收发
        }
#ifdef __USE_DEFAULT_NET_BUILD__
        if (m_NetworkPtr->Init(attr) != RET_OKAY)
        {
#else
        if (m_NetworkPtr->Init(attr, nullptr, MNEW CFrameworkNETPackBuild) != RET_OKAY)
        {
#endif
            LOG_ERROR(m_FileLog, TF("初始化网络模块失败!"));
            return false;
        }
    }
    else
    {
        LOG_ERROR(m_FileLog, TF("加载网络模块失败!"));
        return false;
    }

    if (m_CenterServer != nullptr)
    {
        if (m_CenterServer->Start() == false)
        {
            LOG_ERROR(m_FileLog, TF("启动同步管理服务器服务器失败!"));
            return false;
        }
    }
    if (m_BalanceServer != nullptr)
    {
        if (m_BalanceServer->Start() == false)
        {
            LOG_ERROR(m_FileLog, TF("启动授权均衡服务器服务器失败!"));
            return false;
        }
    }
    if (m_AuthorDBServer != nullptr)
    {
        if (m_AuthorDBServer->Start() == false)
        {
            LOG_ERROR(m_FileLog, TF("启动授权数据服务器服务器失败!"));
            return false;
        }
    }
    if (m_AuthorServer != nullptr)
    {
        if (m_AuthorServer->Start() == false)
        {
            LOG_ERROR(m_FileLog, TF("启动授权网关服务器服务器失败!"));
            return false;
        }
    }
    if (m_MasterDBServer != nullptr)
    {
        if (m_MasterDBServer->Start() == false)
        {
            LOG_ERROR(m_FileLog, TF("启动业务数据服务器服务器失败!"));
            return false;
        }
    }
    if (m_MasterServer != nullptr)
    {
        if (m_MasterServer->Start() == false)
        {
            LOG_ERROR(m_FileLog, TF("启动业务管理服务器服务器失败!"));
            return false;
        }
    }
    if (m_ServiceServer != nullptr)
    {
        if (m_ServiceServer->Start() == false)
        {
            LOG_ERROR(m_FileLog, TF("启动业务功能服务器服务器失败!"));
            return false;
        }
    }
    if (m_GateServer != nullptr)
    {
        if (m_GateServer->Start() == false)
        {
            LOG_ERROR(m_FileLog, TF("启动业务网关服务器服务器失败!"));
            return false;
        }
    }
    return true;
}

void CServerConsole::StopServers(void)
{
    if (m_GateServer != nullptr)
    {
        m_GateServer->Stop();
    }
    if (m_ServiceServer != nullptr)
    {
        m_ServiceServer->Stop();
    }
    if (m_MasterServer != nullptr)
    {
        m_MasterServer->Stop();
    }
    if (m_MasterDBServer != nullptr)
    {
        m_MasterDBServer->Stop();
    }
    if (m_AuthorServer != nullptr)
    {
        m_AuthorServer->Stop();
    }
    if (m_AuthorDBServer != nullptr)
    {
        m_AuthorDBServer->Stop();
    }
    if (m_BalanceServer != nullptr)
    {
        m_BalanceServer->Stop();
    }
    if (m_CenterServer != nullptr)
    {
        m_CenterServer->Stop();
    }
    if (m_NetworkPtr != nullptr)
    {
        m_NetworkPtr->Exit();
    }
}

bool CServerConsole::InitSystems(void)
{
    INIT_CLASS_LOADER( CServerConsole, NET, UUID_OF( CNetworkSystem ), NETWORK_MODULE_NAME);

    LOADER_CLASS_CREEATE(CServerConsole, NET, UUID_OF(CNetwork), m_NetworkPtr.Cast<CComponent>());
    if (m_NetworkPtr == nullptr)
    {
        LOG_ERROR(m_FileLog, TF("加载网络模块失败!"));
        return false;
    }
    m_Config.m_KeyValue.AddItem(CServerConfig::NetworkPtr, (void*)&m_NetworkPtr);

    LOG_INFO(m_FileLog, TF("初始化网络模块完成"));
    return true;
}

void CServerConsole::ExitSystems(void)
{
    if (m_NetworkPtr != nullptr)
    {
        //m_NetworkPtr->Exit();
        m_NetworkPtr = nullptr;
        m_Config.m_KeyValue.Remove(CServerConfig::NetworkPtr);
    }

    EXIT_CLASS_LOADER( CServerConsole, NET );
    LOG_INFO(m_FileLog, TF("释放网络模块完成"));
}


///////////////////////////////////////////////////////////////////////////////////////////////////////////
// _tmain
enum CPU_TECH_EDX
{
    // EDX
    CPUT_RDTSC         = 0x00000010, // CPU_INFO_STDTECH
    CPUT_MMX2          = 0x00400000,
    CPUT_MMX           = 0x00800000,
    CPUT_SSE           = 0x02000000, // CPU_INFO_STDTECH
    CPUT_SSE2          = 0x04000000, // CPU_INFO_STDTECH
    CPUT_HTT           = 0x10000000, // CPU_INFO_STDTECH
    CPUT_3DNOWE        = 0x40000000, // CPU_INFO_EXTTECH
    CPUT_3DNOW         = 0x80000000, // CPU_INFO_EXTTECH
};

enum CPU_TECH_ECX
{
    // ECX, CPUI_STDTECH
    CPUT_SSE3          = 0x00000001,
    CPUT_SSSE3         = 0x00000200,
    CPUT_SSE41         = 0x00080000,
    CPUT_SSE42         = 0x00100000,
    CPUT_SSE4A         = 0x00000040,
};

PCXStr GetCPUVender(UInt uVender)
{
    switch (uVender)
    {
        CASE_RETSTR(CPlatform::CPUV_UNKNOWN, TF("Unknown CPU"));
        CASE_RETSTR(CPlatform::CPUV_INTEL,   TF("Intel CPU"));
        CASE_RETSTR(CPlatform::CPUV_AMD,     TF("AMD CPU"));
        CASE_RETSTR(CPlatform::CPUV_ARM,     TF("ARM CPU"));
    default:
        {
            return TF("Unknown CPU Vender Type");
        }
    }
}

PCXStr GetOSType(UInt uOSType)
{
    switch (uOSType)
    {
        CASE_RETSTR(CPlatform::CPUV_UNKNOWN, TF("Unknown OS"));
        CASE_RETSTR(CPlatform::OST_WINDOWS,  TF("Windows"));
        CASE_RETSTR(CPlatform::OST_LINUX,    TF("Linux"));
        CASE_RETSTR(CPlatform::OST_MAC,      TF("Mac"));
        CASE_RETSTR(CPlatform::OST_IOS,      TF("iOS"));
        CASE_RETSTR(CPlatform::OST_ANDROID,  TF("Android"));
    default:
        {
            return TF("Unknown OS Type");
        }
    }
}

void DumpPlatform(void)
{
    UInt uRuntime = CPlatform::GetRuntimeConfig();
    LOG_INFO(GServerConsoleInst->m_FileLog,  TF("---Platform Information---"));
    LOGV_INFO(GServerConsoleInst->m_FileLog, TF(" %s"), TF(__ARCH_TARGET_STR__));
    LOGV_INFO(GServerConsoleInst->m_FileLog, TF(" %s"), TF(__PLATFORM_TARGET_STR__));
    LOGV_INFO(GServerConsoleInst->m_FileLog, TF(" %s"), TF(__RUNTIME_CHARSET_STR__));
    LOGV_INFO(GServerConsoleInst->m_FileLog, TF(" %s"), (uRuntime & RUNTIME_CONFIG_DEBUG)       ? TF("Debug Status")   : TF("Release Status"));
    LOGV_INFO(GServerConsoleInst->m_FileLog, TF(" %s"), (uRuntime & RUNTIME_CONFIG_STATIC)      ? TF("Static Library") : TF("Dynamic Library"));
    LOGV_INFO(GServerConsoleInst->m_FileLog, TF(" %s"), (uRuntime & RUNTIME_CONFIG_RTTI_HASH64) ? TF("RTTI Hash64")    : TF("RTTI Hash32"));


    CPlatform::CPUINFO cpui;
    CPlatform::GetCPUInfo(cpui);
    LOG_INFO(GServerConsoleInst->m_FileLog,  TF("---CPU Identifier & Features---"));
    LOGV_INFO(GServerConsoleInst->m_FileLog, TF(" %s"), cpui.szBrand);
    LOGV_INFO(GServerConsoleInst->m_FileLog, TF(" Vender : %s, Cores : %d, Speed %dMHz"), GetCPUVender(cpui.usVendor), cpui.usCores, cpui.uSpeed);

    CPlatform::CPUTECH cput;
    CPlatform::GetCPUTech(cput, 1);

    LOGV_INFO(GServerConsoleInst->m_FileLog, TF(" Features : %s, %s, %s, %s, %s, %s, %s, %s, %s"),
              (cput.ullTech[3] & CPUT_RDTSC) ? TF("SSE2[YES]")   : TF("SSE2[NO]"),
              (cput.ullTech[3] & CPUT_MMX)   ? TF("MMX[YES]")    : TF("MMX[NO]"),
              (cput.ullTech[3] & CPUT_SSE)   ? TF("SSE[YES]")    : TF("SSE[NO]"),
              (cput.ullTech[3] & CPUT_SSE2)  ? TF("SSE2[YES]")   : TF("SSE2[NO]"),
              (cput.ullTech[3] & CPUT_HTT)   ? TF("HTT[YES]")    : TF("HTT[NO]"),
              (cput.ullTech[2] & CPUT_SSE3)  ? TF("SSE3[YES]")   : TF("SSE3[NO]"),
              (cput.ullTech[2] & CPUT_SSSE3) ? TF("SSSE3[YES]")  : TF("SSSE3[NO]"),
              (cput.ullTech[2] & CPUT_SSE41) ? TF("SSE41[YES]")  : TF("SSE41[NO]"),
              (cput.ullTech[2] & CPUT_SSE42) ? TF("SSE42[YES]")  : TF("SSE42[NO]"));

    CPlatform::GetCPUTech(cput, 0x80000001);
    LOGV_INFO(GServerConsoleInst->m_FileLog, TF(" Features : %s, %s, %s, %s, %s"),
              (cput.ullTech[3] & CPUT_MMX)   ? TF("MMX[YES]")    : TF("MMX[NO]"),
              (cput.ullTech[3] & CPUT_MMX2)  ? TF("MMX2[YES]")   : TF("MMX2[NO]"),
              (cput.ullTech[3] & CPUT_3DNOW) ? TF("3DNOW[YES]")  : TF("3DNOW[NO]"),
              (cput.ullTech[3] & CPUT_3DNOWE)? TF("3DNOW+[YES]") : TF("3DNOW+[NO]"),
              (cput.ullTech[2] & CPUT_SSE4A) ? TF("SSE4A[YES]")  : TF("SSE4A[NO]"));

    CPlatform::MEMINFO mem;
    CPlatform::GetMemInfo(mem);
    LOG_INFO(GServerConsoleInst->m_FileLog, TF("---Memory Information---"));
    LOGV_INFO(GServerConsoleInst->m_FileLog, TF(" Memory Current Used       : %8d[%%]"), mem.uUsedPercent);
    LOGV_INFO(GServerConsoleInst->m_FileLog, TF(" Memory Page Size          : %8d[KB]"), mem.uPageSize);
    LOGV_INFO(GServerConsoleInst->m_FileLog, TF(" Memory Total Physical Size: %8d[MB]"), mem.uTotalPhys);
    LOGV_INFO(GServerConsoleInst->m_FileLog, TF(" Memory Avail Physical Size: %8d[MB]"), mem.uAvailPhys);

    CPlatform::OSINFO os;
    CPlatform::GetOSInfo(os);
    LOG_INFO(GServerConsoleInst->m_FileLog, TF("---Operation System Information---"));
    LOGV_INFO(GServerConsoleInst->m_FileLog, TF(" OS Type        : %s"),             GetOSType(os.uOSType));
    LOGV_INFO(GServerConsoleInst->m_FileLog, TF(" OS Version     : %d.%d Build %d"), os.uMajor, os.uMinor, os.uBuild);
    LOGV_INFO(GServerConsoleInst->m_FileLog, TF(" OS Description : %s"),             os.szDescription);

    CPlatform::TIMEINFO time;
    CPlatform::GetTimeInfo(time);
    LOGV_INFO(GServerConsoleInst->m_FileLog, TF("Time : %d-%d-%d(%d), %d:%d:%d:%d"), time.usYear, time.usMonth, time.usDay, time.usWeekDay, time.usHour, time.usMinute, time.usSecond, time.usMSecond);
}

#if (__PLATFORM_TARGET__ == PLATFORM_TARGET_WINDOWS)

BOOL WINAPI ConsoleHandler(DWORD dwCtrlType)
{
    GServerConsoleInst->Stop();
    CPlatform::SleepEx(100);
    //GServerConsoleInst->Exit();
    //CoreExit();

    //CSEHExceptionFilter::Exit();
    return FALSE;
}

#else

void SIGTERMHandler(Int)
{
    GServerConsoleInst->Stop();
    CPlatform::SleepEx(100);
}

#define _tmain   main

#endif

Int _tmain(Int argc, XChar* argv[])
{
#if (__PLATFORM_TARGET__ == PLATFORM_TARGET_WINDOWS)
    CSEHExceptionFilter::Init();

    ::SetConsoleCtrlHandler(ConsoleHandler, TRUE);
    CPlatform::SetExceptHandler(&CServerConsole::ThreadExceptHandler);
    DumpPlatform();
#else
    signal(SIGPIPE, SIG_IGN);
    signal(SIGTERM, SIGTERMHandler);

    CExceptionTerminater::Init();
#endif

    CoreInit();
    if (GServerConsoleInst->Init(argc, argv))
    {
        GServerConsoleInst->Start();
    }
    GServerConsoleInst->Exit();
    CoreExit();

#if (__PLATFORM_TARGET__ == PLATFORM_TARGET_WINDOWS)
    CSEHExceptionFilter::Exit();
#else
    CExceptionTerminater::Exit();
#endif
    return 0;
}




